﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using iDMS.Models;
using System.Web.Security;

namespace iDMS.Controllers
{
    [CustomAuthorize(Roles = "Normal User")]
    public class DesignChangeController : Controller
    {
        DMSRepository db = new DMSRepository();
        const string errNoPerm = "You have no permision to access this Site";
        const string errNoEmployee = "Please register";
        const string errNoPending = "Design Change is not in Pending phase";
        const string errNoRQST = "Design Change is not in RQST Step";
        const string errOcured = "An error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
       

        public ActionResult Index(string search)
        {
            var list = db.DesignChangesGetAll();
            ViewBag.TotalNumber = list.Count();
            if (!string.IsNullOrEmpty(search))
            {
                list = list.Where(m => m.Title.ToUpper().Contains(search.ToUpper()) || m.Identifier.ToUpper().Contains(search.ToUpper()));
            }

            list = list.OrderBy(m => m.Identifier);

            return View(list.ToList());
        }

        public ActionResult Newest(int amount)
        {
            var list = db.DesignChangesGetAll();
            

            list = list.OrderByDescending(m => m.LastModified);

            if (amount > 1)
            {
                list = list.Take(amount);
            }
            return View("Index", list.ToList());
        }

        public ActionResult IndexByPhase(int id)
        {
            var list = db.DesignChangesGetAll();

            if (!db.PhasesGetAll().Where(p => p.PhaseID == id).Any())
            {
                return HttpNotFound();
            }

            list = list.Where(d => d.PhaseID == id);


            list = list.OrderByDescending(m => m.Identifier);

            
            return View("Index", list.ToList());
        }

        public ActionResult ShowExpired()
        {
            var list = db.DesignChangesGetAll();

            

            list = list.Where(d => d.PlannedReleaseDate < DateTime.Now  && d.PhaseID > 1 && d.PhaseID <5);


            list = list.OrderBy(m => m.PlannedReleaseDate);


            return View("Index", list.ToList());
        }

        public ActionResult Details(int id)
        {
            DesignChange model = db.DesignChangesGetAll().SingleOrDefault(d => d.DesignChangeID == id);
            if (model == null)
            {
                return HttpNotFound();
            }
            List<DesignChangeLog> logs = db.DesignChangesLogsGetAll().Where(d => d.ChangeID == id).ToList();
            ViewBag.History = logs;
            List<WorkflowStep> allowedSteps = db.WorkflowStepsGetAll().Where(s => s.PhaseFrom == model.PhaseID).ToList();
            ViewBag.AllowedSteps = allowedSteps;
            ViewBag.Notes = db.NotesGetAll().Where(n => n.DesignChangeID == id).ToList();
            return View(model);
        }

        public ActionResult DetailsWindow(int id)
        {
            DesignChange model = db.DesignChangesGetAll().SingleOrDefault(d => d.DesignChangeID == id);
            if (model == null)
            {
                return HttpNotFound();
            }
            return PartialView("_DetailsWindow", model);
        }

        private List<SelectListItem> populateChangeReasons()
        {
            List<DesignChangeReason> r = db.ReasonsGetAll().ToList();
            List<SelectListItem> reasons = new List<SelectListItem>();
            foreach (DesignChangeReason item in r)
            {
                SelectListItem newItem = new SelectListItem();
                newItem.Text = item.Name;
                newItem.Value = item.ReasonID.ToString();
                reasons.Add(newItem);
            }
            return reasons;
        }


        public ActionResult Create()
        {
            if (!User.IsInRole("Creation"))
            {
                ViewBag.Message = errNoPerm;
                return View("Message");
            }
            ViewBag.Reasons = populateChangeReasons();
            DesignChange model = new DesignChange();
            model.PlannedReleaseDate = DateTime.Now.AddMonths(3);
            return View(model);
        }

        [HttpPost]
        public ActionResult Create(FormCollection collection)
        {
            if (!User.IsInRole("Creation"))
            {
                ViewBag.Message = errNoPerm;
                return View("Message");
            }
            Employee employee = db.EmployeesGetAll().SingleOrDefault(e => e.UserGUID == (Guid)Membership.GetUser().ProviderUserKey);
            if (employee == null)
            {
                ViewBag.Message = errNoEmployee;
                return View("Message");
            }
            DesignChange model = new DesignChange();
            UpdateModel<DesignChange>(model);
            model.CreateDate = DateTime.Now;
            model.LastModified = DateTime.Now;
            model.PhaseID = 0; //RQST
            model.ChangeBuilderEmployeeID = employee.EmployeeID;
            bool succeded;
            try
            {
                db.DesignChangeAdd(model);
                db.CommitChanges();
                succeded = true;                
            }
            catch
            {
                succeded = false;
            }
            if (succeded)
            {
                return RedirectToAction("Details", new { id = model.DesignChangeID });
            }
            else
            {
                ModelState.AddModelError("", errOcured);
            }
            return View(model);
        }

        public ActionResult Edit(int id)
        {
            DesignChange entity = db.DesignChangesGetAll().SingleOrDefault(d => d.DesignChangeID == id);//db.FindDesignChange(id);
            if (entity == null)
            {
                return HttpNotFound();
            }
            if (entity.PhaseID != 0)
            {
                ViewBag.Message = errNoRQST;
                return View("Message");
            }
            else
            {
                ViewBag.Reasons = populateChangeReasons();
                return View(entity);
            }

        }

        [HttpPost]
        public ActionResult Edit(int id, FormCollection collection)
        {
            try
            {
                DesignChange entity = db.DesignChangesGetAll().SingleOrDefault(d => d.DesignChangeID == id);
                if (entity == null)
                {
                    return HttpNotFound();
                }
                UpdateModel(entity);
                entity.LastModified = DateTime.Now;
                db.CommitChanges();
                return RedirectToAction("Details", new { id = entity.DesignChangeID });
            }
            catch
            {
                ViewBag.Message = "There was an Error";
                return View("Message");
            }
        }

        public ActionResult StepPerform(int id, byte phase)
        {
            DesignChange entity = db.DesignChangesGetAll().SingleOrDefault(d => d.DesignChangeID == id);
            if (entity == null)
            {
                return HttpNotFound();
            }
            WorkflowWrapper wrapper;
            try
            {
                wrapper = new WorkflowWrapper(db, entity, phase,User);
            }
            catch (Exception)
            {
                ViewBag.Message = "Step not Allowed";
                return View("Message");
            }
            WorkflowPrerequisitesResult result = wrapper.CheckPrerequisites();
            if (result == WorkflowPrerequisitesResult.Passed)
            {
                return View(wrapper.GetViewModel());
            }
            else
            {
                ViewBag.Message = "Prerequisites not met: " + ErrorCodeToString(result);
                return View("Message");
            }
        }


        [HttpPost]
        public ActionResult StepPerform(int id, byte phase, FormCollection collection)
        {
            DesignChange entity = db.DesignChangesGetAll().SingleOrDefault(d => d.DesignChangeID == id);
            if (entity == null)
            {
                return HttpNotFound();
            }
            WorkflowWrapper wrapper;
            try
            {
                wrapper = new WorkflowWrapper(db, entity, phase,User);
            }
            catch (Exception)
            {
                ViewBag.Message = "Step not Allowed";
                return PartialView("_Message");
            }
            DesignChangeStepViewModel viewModel = wrapper.GetViewModel();
            UpdateModel(viewModel);
            Employee employee = db.EmployeesGetAll().SingleOrDefault(e => e.UserGUID == (Guid)Membership.GetUser().ProviderUserKey);
            if (employee == null)
            {
                ViewBag.Message = errNoEmployee;
                return PartialView("_Message");
            }
            bool succeded;
            try
            {
                wrapper.DoStep(employee, viewModel.Comment);
                db.CommitChanges();
                Mailer mailer = new Mailer(db);
                String body = "Design Change: "+viewModel.DesignChange.IndentifierAndTitle + " has been moved to phase: "+viewModel.DesignChange.DesignChangePhase.FullName;
                mailer.SendToEmployee(viewModel.DesignChange.ChangeBuilderEmployeeID, "iDMS Workflow info", body);
                succeded = true;
            }
            catch
            {
                succeded = false;
            }
            if (succeded)
            {
                return PartialView("_StepPerformSuccess", viewModel);
            }
            else
            {
                ViewBag.Message = errOcured;
                return PartialView("_Message");
            }
        }

        public ActionResult AddNote(int id)
        {
            DesignChange entity = db.DesignChangesGetAll().SingleOrDefault(d => d.DesignChangeID == id);
            if (entity == null)
            {
                return HttpNotFound();
            }
            ViewBag.DesignChange = entity;
            return View();
        }


        [HttpPost]
        public ActionResult AddNote(int id, FormCollection collection)
        {
            Employee employee = db.EmployeesGetAll().SingleOrDefault(e => e.UserGUID == (Guid)Membership.GetUser().ProviderUserKey);
            if (employee == null)
            {
                ViewBag.Message = errNoEmployee;
                return View("Message");
            }
            Note newNote = new Note();
            UpdateModel(newNote);
            newNote.Date = DateTime.Now;

            newNote.EmployeeID = employee.EmployeeID;
            newNote.DesignChangeID = id;
            try
            {
                db.NoteAdd(newNote);
                db.CommitChanges();
                return RedirectToAction("Details", new { id = id });
            }
            catch
            {
                return View();
            }
        }

        public ActionResult AllNotes(int id)
        {
            var list = db.NotesGetAll().Where(n => n.DesignChangeID == id);
            return View(list);
        }

        private static string ErrorCodeToString(WorkflowPrerequisitesResult result)
        {
            switch (result)
            {
                case WorkflowPrerequisitesResult.NothingChanged:
                    return "Nothing Changed";
                case WorkflowPrerequisitesResult.Fail:
                    return "Something failed";
                case WorkflowPrerequisitesResult.UserNotInRole:
                    return "User not in Required Role";
                case WorkflowPrerequisitesResult.UploadNotDone:
                    return "At least one sheet does not have the uploaded file";
                default:
                    return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator";
            }
        }
    }
}
